package com.example.myblog.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.example.myblog.exception.BaseException;
import com.example.myblog.result.BaseCodeEnum;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author yx
 */
@Component
public class RedisUtils {
    private static final ObjectMapper mapper = new ObjectMapper();
    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }


    StringRedisTemplate stringRedisTemplate;

    /**
     * 不限制过期时间的存储,String 形式
     * @param key
     * @param value
     * @throws JsonProcessingException
     */
    public void load(String key, Object value) throws JsonProcessingException {
        String valueOfKey = mapper.writeValueAsString(value);
        this.stringRedisTemplate.opsForValue().set(key,valueOfKey);
    }

    /**
     * 限制过期时间的存储, String 形式
     * @param key
     * @param value
     * @param time
     * @param unit
     * @throws JsonProcessingException
     */
    public void load(String key,Object value,long time,TimeUnit unit) throws JsonProcessingException {
        String valueOfKey = mapper.writeValueAsString(value);
        this.stringRedisTemplate.opsForValue().set(key,valueOfKey,time,unit);
    }

    /**
     * 不限制过期时间的存储，hash形式
     * @param key
     * @param value
     */
    public void loadByHash(String key,Object value) {
        Map<String,Object> map = BeanUtil.beanToMap(value,
                new HashMap<>(16),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName,fieldValue) -> {
                            if (fieldValue == null){
                                return null;
                            }
                            return fieldValue.toString();
                        }));
        stringRedisTemplate.opsForHash().putAll(key,map);
    }

    /**
     * 限制过期时间的存储，hash 形式
     * @param key
     * @param value
     * @param time
     * @param unit
     */
    public void loadByHash(String key,Object value,long time,TimeUnit unit) {
        Map<String,Object> map = BeanUtil.beanToMap(value,
                new HashMap<>(16),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName,fieldValue) -> {
                            if (fieldValue == null){
                                return null;
                            }
                            return fieldValue.toString();
                        }));
        stringRedisTemplate.opsForHash().putAll(key,map);
        stringRedisTemplate.expire(key,time,unit);
    }

    /**
     * 获取值，String 形式
     * @param key
     * @param t
     * @return
     * @param <T>
     * @throws JsonProcessingException
     */
    public <T> T  getValue(String key,Class<T> c) throws JsonProcessingException, BaseException {
        String valueOfKey = this.stringRedisTemplate.opsForValue().get(key);
        Object o = mapper.readValue(valueOfKey, c);
        if (o == null) {
            throw new BaseException(BaseCodeEnum.BAD_REQUEST);
        }
        T value = (T)o;
        return value;
    }

    /**
     * 获取值，hash 形式
     * @param key
     * @param t
     * @return
     * @param <T>
     * @throws JsonProcessingException
     * @throws BaseException
     */
    public <T> T  getValueByHash(String key,T t) throws JsonProcessingException, BaseException {
        Map<Object, Object> map = this.stringRedisTemplate.opsForHash().entries(key);
        if (map.isEmpty()) {
            throw new BaseException(BaseCodeEnum.NOT_FOUND);
        }
        T value = BeanUtil.fillBeanWithMap(map, t, false);
        return value;
    }

    /**
     * 需要返回null来做特殊处理
     * @param key
     * @param t
     * @return
     * @param <T>
     */
    public <T> T  getValueByHashNotThrow(String key,T t)  {
        Map<Object, Object> map = this.stringRedisTemplate.opsForHash().entries(key);
        if (map.isEmpty()) {
            return null;
        }
        T value = BeanUtil.fillBeanWithMap(map, t, false);
        return value;
    }
    /**
     * 设置key的有效期
     * @param key
     * @param time
     * @param unit
     */
    public void expire(String key,long time,TimeUnit unit) {
        this.stringRedisTemplate.expire(key,time,unit);
    }

}
